<!doctype html>



  


<html class="theme-next muse use-motion" lang="zh-Hans">
<head>
  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>









<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />




  
  
  
  

  
    
    
  

  

  

  

  

  
    
    
    <link href="//fonts.googleapis.com/css?family=Lato:300,300italic,400,400italic,700,700italic&subset=latin,latin-ext" rel="stylesheet" type="text/css">
  






<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />

<link href="/css/main.css?v=5.1.1" rel="stylesheet" type="text/css" />


  <meta name="keywords" content="java," />








  <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico?v=5.1.1" />






<meta name="description" content="原文:http://www.cnblogs.com/Qian123/p/5710533.html假如说你想复制一个简单变量。很简单：  int apples = 5;int pears = apples;   不仅仅是int类型，其它七种原始数据类型(boolean,char,byte,short,float,double.long)同样适用于该类情况。 但是如果你复制的是一个对象，情况就有些复杂">
<meta name="keywords" content="java">
<meta property="og:type" content="article">
<meta property="og:title" content="Java对象克隆详解(转)">
<meta property="og:url" content="http://yoursite.com/2017/07/24/Java对象克隆详解/index.html">
<meta property="og:site_name" content="xuwujing&#39;s blog">
<meta property="og:description" content="原文:http://www.cnblogs.com/Qian123/p/5710533.html假如说你想复制一个简单变量。很简单：  int apples = 5;int pears = apples;   不仅仅是int类型，其它七种原始数据类型(boolean,char,byte,short,float,double.long)同样适用于该类情况。 但是如果你复制的是一个对象，情况就有些复杂">
<meta property="og:image" content="http://common.cnblogs.com/images/copycode.gif">
<meta property="og:image" content="http://common.cnblogs.com/images/copycode.gif">
<meta property="og:image" content="http://images2015.cnblogs.com/blog/690102/201607/690102-20160727114833309-1421006998.png">
<meta property="og:image" content="http://common.cnblogs.com/images/copycode.gif">
<meta property="og:image" content="http://common.cnblogs.com/images/copycode.gif">
<meta property="og:image" content="http://common.cnblogs.com/images/copycode.gif">
<meta property="og:image" content="http://common.cnblogs.com/images/copycode.gif">
<meta property="og:image" content="http://common.cnblogs.com/images/copycode.gif">
<meta property="og:image" content="http://common.cnblogs.com/images/copycode.gif">
<meta property="og:image" content="http://common.cnblogs.com/images/copycode.gif">
<meta property="og:image" content="http://common.cnblogs.com/images/copycode.gif">
<meta property="og:image" content="http://common.cnblogs.com/images/copycode.gif">
<meta property="og:image" content="http://common.cnblogs.com/images/copycode.gif">
<meta property="og:image" content="http://images2015.cnblogs.com/blog/690102/201607/690102-20160727132640216-1387063948.png">
<meta property="og:image" content="http://images2015.cnblogs.com/blog/690102/201607/690102-20160727132838528-120069275.png">
<meta property="og:image" content="http://common.cnblogs.com/images/copycode.gif">
<meta property="og:image" content="http://common.cnblogs.com/images/copycode.gif">
<meta property="og:image" content="http://common.cnblogs.com/images/copycode.gif">
<meta property="og:image" content="http://common.cnblogs.com/images/copycode.gif">
<meta property="og:updated_time" content="2017-08-19T06:39:06.632Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Java对象克隆详解(转)">
<meta name="twitter:description" content="原文:http://www.cnblogs.com/Qian123/p/5710533.html假如说你想复制一个简单变量。很简单：  int apples = 5;int pears = apples;   不仅仅是int类型，其它七种原始数据类型(boolean,char,byte,short,float,double.long)同样适用于该类情况。 但是如果你复制的是一个对象，情况就有些复杂">
<meta name="twitter:image" content="http://common.cnblogs.com/images/copycode.gif">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Muse',
    sidebar: {"position":"left","display":"post","offset":12,"offset_float":0,"b2t":false,"scrollpercent":false},
    fancybox: true,
    motion: true,
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="http://yoursite.com/2017/07/24/Java对象克隆详解/"/>





  <title>Java对象克隆详解(转) | xuwujing's blog</title>
  





  <script type="text/javascript">
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "https://hm.baidu.com/hm.js?39c177d10f6e05ddfa113e02139b9c1c";
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(hm, s);
    })();
  </script>










</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail ">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/"  class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">xuwujing's blog</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle"></p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br />
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br />
            
            分类
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
            
            归档
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/tags/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br />
            
            标签
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
    <link itemprop="mainEntityOfPage" href="http://yoursite.com/2017/07/24/Java对象克隆详解/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="xuwujing">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/xuwujing.png">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="xuwujing's blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">Java对象克隆详解(转)</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2017-07-24T12:47:00+08:00">
                2017-07-24
              </time>
            

            

            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/java/" itemprop="url" rel="index">
                    <span itemprop="name">java</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    <div class="post-body" itemprop="articleBody">

      
      

      
        <p>原文:<a href="http://www.cnblogs.com/Qian123/p/5710533.html" target="_blank" rel="external">http://www.cnblogs.com/Qian123/p/5710533.html</a><br></p><p>假如说你想复制一个简单变量。很简单：</p><p></p>
<p><div class="cnblogs_code"></div></p>
<p><pre><span style="color: #0000ff;">int</span> apples = 5<span style="color: #000000;">;<br></span><span style="color: #0000ff;">int</span> pears = apples;  </pre><br></p>
<p></p><p>不仅仅是int类型，其它七种原始数据类型(boolean,char,byte,short,float,double.long)同样适用于该类情况。</p><p></p>
<p></p><p>但是如果你复制的是一个对象，情况就有些复杂了。</p><p></p>
<p></p><p>假设说我是一个beginner，我会这样写：</p><p></p>
<p><div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码" target="_blank" rel="external"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div></div></p>
<p><pre><span style="color: #0000ff;">class</span><span style="color: #000000;"> Student {<br>    </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> number;  </span></pre></p>
<pre><code>&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; getNumber() {  
    &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; number;  
}  

&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;void&lt;/span&gt; setNumber(&lt;span style=&quot;color: #0000ff;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; number) {  
    &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;this&lt;/span&gt;.number =&lt;span style=&quot;color: #000000;&quot;&gt; number;  
}  
</code></pre><p>}<br><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> Test {  </span></p>
<pre><code>&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; main(String args[]) {  
    Student stu1 &lt;/span&gt;= &lt;span style=&quot;color: #0000ff;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; Student();  
    stu1.setNumber(&lt;/span&gt;12345&lt;span style=&quot;color: #000000;&quot;&gt;);  
    Student stu2 &lt;/span&gt;=&lt;span style=&quot;color: #000000;&quot;&gt; stu1;  

    System.out.println(&lt;/span&gt;&quot;学生1:&quot; +&lt;span style=&quot;color: #000000;&quot;&gt; stu1.getNumber());  
    System.out.println(&lt;/span&gt;&quot;学生2:&quot; +&lt;span style=&quot;color: #000000;&quot;&gt; stu2.getNumber());  
}  
</code></pre><p>}  </p>
<p><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码" target="_blank" rel="external"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div></p>
<p></p><p>结果：</p><p></p>
<p></p><p class="alt">学生1:12345 &nbsp;</p><p></p>
<p></p><p class="alt">学生2:12345 &nbsp;</p><p></p>
<p></p><p>&nbsp;</p><p></p>
<p></p><p>这里我们自定义了一个学生类，该类只有一个number字段。</p><p></p>
<p></p><p>我们新建了一个学生实例，然后将该值赋值给stu2实例。(Student stu2 = stu1;)</p><p></p>
<p></p><p>再看看打印结果，作为一个新手，拍了拍胸腹，对象复制不过如此，</p><p></p>
<p></p><p>难道真的是这样吗？</p><p></p>
<p></p><p>我们试着改变stu2实例的number字段，再打印结果看看：</p><p></p>
<p><div class="cnblogs_code"></div></p>
<p><pre>stu2.setNumber(54321<span style="color: #000000;">);  </span></pre></p>
<p>System.out.println(“学生1:” +<span style="color: #000000;"> stu1.getNumber());<br>System.out.println(</span>“学生2:” + stu2.getNumber());  <br></p>
<p></p><p>结果：</p><p></p>
<p></p><p class="alt">学生1:54321 &nbsp;</p><p></p>
<p></p><p class="alt">学生2:54321 &nbsp;</p><p></p>
<p></p><p class="alt">这就怪了，为什么改变学生2的学号，学生1的学号也发生了变化呢？</p><p></p>
<p></p><p>原因出在(stu2 = stu1) 这一句。该语句的作用是将stu1的引用赋值给stu2，</p><p></p>
<p></p><p>这样，stu1和stu2指向内存堆中同一个对象。如图：</p><p></p>
<p></p><p><img src="http://images2015.cnblogs.com/blog/690102/201607/690102-20160727114833309-1421006998.png" alt="" width="322" height="253"></p><p></p>
<p></p><p>那么，怎样才能达到复制一个对象呢？</p><p></p>
<p></p><p>是否记得万类之王Object。它有11个方法，有两个protected的方法，其中一个为clone方法。</p><p></p>
<p></p><p>在Java中所有的类都是缺省的继承自Java语言包中的Object类的，查看它的源码，你可以把你的JDK目录下的src.zip复制到其他地方然后解压，里面就是所有的源码。发现里面有一个访问限定符为protected的方法clone()：</p><p></p>
<p><div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码" target="_blank" rel="external"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div></div></p>
<p><pre><span style="color: #008000;">/<em></em></span><span style="color: #008000;"><br>Creates and returns a copy of this object. The precise meaning of “copy” may depend on the class of the object.<br>The general intent is that, for any object x, the expression:<br>1) x.clone() != x will be true<br>2) x.clone().getClass() == x.getClass() will be true, but these are not absolute requirements.<br>3) x.clone().equals(x) will be true, this is not an absolute requirement.<br></span><span style="color: #008000;">/</span><br><span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">native</span> Object clone() <span style="color: #0000ff;">throws</span> CloneNotSupportedException;</pre></p>
<p><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码" target="_blank" rel="external"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div></p>
<p></p><p>仔细一看，它还是一个native方法，大家都知道native方法是非Java语言实现的代码，供Java程序调用的，因为Java程序是运行在JVM虚拟机上面的，要想访问到比较底层的与操作系统相关的就没办法了，只能由靠近操作系统的语言来实现。</p><p></p>
<p><ol></ol></p>
<p><li>第一次声明保证克隆对象将有单独的内存地址分配。</li></p>
<p><li>第二次声明表明，原始和克隆的对象应该具有相同的类类型，但它不是强制性的。</li></p>
<p><li>第三声明表明，原始和克隆的对象应该是平等的equals()方法使用，但它不是强制性的。</li><br></p>
<p></p><p>因为每个类直接或间接的父类都是Object，因此它们都含有clone()方法，但是因为该方法是protected，所以都不能在类外进行访问。</p><p></p>
<p></p><p>要想对一个对象进行复制，就需要对clone方法覆盖。</p><p></p>
<p><div style="text-align: right"><a href="#_labelTop" style="color:blue">回到顶部</a><a name="_label0"></a></div></p><h2 id="blogTitle0">为什么要克隆？</h2><p></p>
<p></p><p>　　大家先思考一个问题，为什么需要克隆对象？直接new一个对象不行吗？</p><p></p>
<p></p><p>　　答案是：克隆的对象可能包含一些已经修改过的属性，而new出来的对象的属性都还是初始化时候的值，所以当需要一个新的对象来保存当前对象的“状态”就靠clone方法了。那么我把这个对象的临时属性一个一个的赋值给我新new的对象不也行嘛？可以是可以，但是一来麻烦不说，二来，大家通过上面的源码都发现了clone是一个native方法，就是快啊，在底层实现的。</p><p></p>
<p></p><p>　　提个醒，我们常见的Object a=new Object();Object b;b=a;这种形式的代码复制的是引用，即对象在内存中的地址，a和b对象仍然指向了同一个对象。</p><p></p>
<p></p><p>　　而通过clone方法赋值的对象跟原来的对象时同时独立存在的。</p><p></p>
<p><div style="text-align: right"><a href="#_labelTop" style="color:blue">回到顶部</a><a name="_label1"></a></div></p><h2 id="blogTitle1">如何实现克隆</h2><p></p>
<p></p><p>先介绍一下两种不同的克隆方法，<strong>浅克隆(ShallowClone)</strong>和<strong>深克隆(DeepClone)</strong>。</p><p></p>
<p></p><p>在Java语言中，数据类型分为值类型（基本数据类型）和引用类型，值类型包括int、double、byte、boolean、char等简单数据类型，引用类型包括类、接口、数组等复杂类型。浅克隆和深克隆的主要区别在于是否支持引用类型的成员变量的复制，下面将对两者进行详细介绍。</p><p></p>
<p></p><p>一般步骤是（浅克隆）：</p><p></p>
<p></p><p>1. <strong>被复制的类需要实现Clonenable接口</strong>（不实现的话在调用clone方法会抛出CloneNotSupportedException异常)， 该接口为标记接口(不含任何方法)</p><p></p>
<p></p><p>2. <strong>覆盖clone()方法，访问修饰符设为public</strong>。<strong>方法中调用super.clone()方法得到需要的复制对象</strong>。（native为本地方法)</p><p></p>
<p></p><p>下面对上面那个方法进行改造：</p><p></p>
<p><div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码" target="_blank" rel="external"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div></div></p>
<p><pre><span style="color: #0000ff;">class</span> Student <span style="color: #0000ff; background-color: #ffff99;">implements</span><span style="color: #000000;"><span style="background-color: #ffff99;"> Cloneable</span>{<br>    </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> number;  </span></pre></p>
<pre><code>&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; getNumber() {  
    &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; number;  
}  

&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #0000ff;&quot;&gt;void&lt;/span&gt; setNumber(&lt;span style=&quot;color: #0000ff;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; number) {  
    &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;this&lt;/span&gt;.number =&lt;span style=&quot;color: #000000;&quot;&gt; number;  
}  

@Override  
&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; Object &lt;span style=&quot;background-color: #ffff99;&quot;&gt;clone&lt;/span&gt;() {  
    Student stu &lt;/span&gt;= &lt;span style=&quot;color: #0000ff;&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;;  
    &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;try&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;{  
        stu &lt;/span&gt;= (Student)&lt;span style=&quot;color: #0000ff; background-color: #ffff99;&quot;&gt;super&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffff99;&quot;&gt;.clone()&lt;/span&gt;;  
    }&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;catch&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(CloneNotSupportedException e) {  
        e.printStackTrace();  
    }  
    &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; stu;  
}  
</code></pre><p>}<br><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> Test {<br>    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String args[]) {<br>        Student stu1 </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> Student();<br>        stu1.setNumber(</span>12345<span style="color: #000000;">);<br>        Student stu2 </span>=<span style="color: #000000;"> (Student)stu1.clone();  </span></p>
<pre><code>    System.out.println(&lt;/span&gt;&quot;学生1:&quot; +&lt;span style=&quot;color: #000000;&quot;&gt; stu1.getNumber());  
    System.out.println(&lt;/span&gt;&quot;学生2:&quot; +&lt;span style=&quot;color: #000000;&quot;&gt; stu2.getNumber());  

    stu2.setNumber(&lt;/span&gt;54321&lt;span style=&quot;color: #000000;&quot;&gt;);  

    System.out.println(&lt;/span&gt;&quot;学生1:&quot; +&lt;span style=&quot;color: #000000;&quot;&gt; stu1.getNumber());  
    System.out.println(&lt;/span&gt;&quot;学生2:&quot; +&lt;span style=&quot;color: #000000;&quot;&gt; stu2.getNumber());  
}  
</code></pre><p>}  </p>
<p><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码" target="_blank" rel="external"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div></p>
<p></p><p>结果：</p><p></p>
<p></p><p class="alt">学生1:12345&nbsp;&nbsp;</p><p></p>
<p></p><p>学生2:12345&nbsp;&nbsp;</p><p></p>
<p></p><p class="alt">学生1:12345&nbsp;&nbsp;</p><p></p>
<p></p><p>学生2:54321</p><p></p>
<p></p><p>如果你还不相信这两个对象不是同一个对象，那么你可以看看这一句：</p><p></p>
<p><div class="cnblogs_code"></div></p>
<p><pre>System.out.println(stu1 == stu2); <span style="color: #008000;">//</span><span style="color: #008000;"> false  </span></pre><br></p>
<p></p><p>上面的复制被称为浅克隆。</p><p></p>
<p></p><p>还有一种稍微复杂的深度复制：</p><p></p>
<p></p><p>我们在学生类里再加一个Address类。</p><p></p>
<p><div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码" target="_blank" rel="external"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div></div></p>
<p><pre><span style="color: #008080;"> 1</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> Address  {<br></span><span style="color: #008080;"> 2</span>     <span style="color: #0000ff;">private</span><span style="color: #000000;"> String add;<br></span><span style="color: #008080;"> 3</span><br><span style="color: #008080;"> 4</span>     <span style="color: #0000ff;">public</span><span style="color: #000000;"> String getAdd() {<br></span><span style="color: #008080;"> 5</span>         <span style="color: #0000ff;">return</span><span style="color: #000000;"> add;<br></span><span style="color: #008080;"> 6</span> <span style="color: #000000;">    }<br></span><span style="color: #008080;"> 7</span><br><span style="color: #008080;"> 8</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> setAdd(String add) {<br></span><span style="color: #008080;"> 9</span>         <span style="color: #0000ff;">this</span>.add =<span style="color: #000000;"> add;<br></span><span style="color: #008080;">10</span> <span style="color: #000000;">    }<br></span><span style="color: #008080;">11</span><br><span style="color: #008080;">12</span> <span style="color: #000000;">}<br></span><span style="color: #008080;">13</span><br><span style="color: #008080;">14</span> <span style="color: #0000ff;">class</span> Student <span style="color: #0000ff;">implements</span><span style="color: #000000;"> Cloneable{<br></span><span style="color: #008080;">15</span>     <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> number;<br></span><span style="color: #008080;">16</span><br><span style="color: #008080;">17</span>     <span style="color: #0000ff; background-color: #ffff99;">private</span><span style="color: #000000;"><span style="background-color: #ffff99;"> Address addr; </span><br></span><span style="color: #008080;">18</span><br><span style="color: #008080;">19</span>     <span style="color: #0000ff;">public</span><span style="color: #000000;"> Address getAddr() {<br></span><span style="color: #008080;">20</span>         <span style="color: #0000ff;">return</span><span style="color: #000000;"> addr;<br></span><span style="color: #008080;">21</span> <span style="color: #000000;">    }<br></span><span style="color: #008080;">22</span><br><span style="color: #008080;">23</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> setAddr(Address addr) {<br></span><span style="color: #008080;">24</span>         <span style="color: #0000ff;">this</span>.addr =<span style="color: #000000;"> addr;<br></span><span style="color: #008080;">25</span> <span style="color: #000000;">    }<br></span><span style="color: #008080;">26</span><br><span style="color: #008080;">27</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> getNumber() {<br></span><span style="color: #008080;">28</span>         <span style="color: #0000ff;">return</span><span style="color: #000000;"> number;<br></span><span style="color: #008080;">29</span> <span style="color: #000000;">    }<br></span><span style="color: #008080;">30</span><br><span style="color: #008080;">31</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> setNumber(<span style="color: #0000ff;">int</span><span style="color: #000000;"> number) {<br></span><span style="color: #008080;">32</span>         <span style="color: #0000ff;">this</span>.number =<span style="color: #000000;"> number;<br></span><span style="color: #008080;">33</span> <span style="color: #000000;">    }<br></span><span style="color: #008080;">34</span><br><span style="color: #008080;">35</span> <span style="color: #000000;">    @Override<br></span><span style="color: #008080;">36</span>     <span style="color: #0000ff;">public</span><span style="color: #000000;"> Object clone() {<br></span><span style="color: #008080;">37</span>         Student stu = <span style="color: #0000ff;">null</span><span style="color: #000000;">;<br></span><span style="color: #008080;">38</span>         <span style="color: #0000ff;">try</span><span style="color: #000000;">{<br></span><span style="color: #008080;">39</span>             stu = (Student)<span style="color: #0000ff;">super</span><span style="color: #000000;">.clone();<br></span><span style="color: #008080;">40</span>         }<span style="color: #0000ff;">catch</span><span style="color: #000000;">(CloneNotSupportedException e) {<br></span><span style="color: #008080;">41</span> <span style="color: #000000;">            e.printStackTrace();<br></span><span style="color: #008080;">42</span> <span style="color: #000000;">        }<br></span><span style="color: #008080;">43</span>         <span style="color: #0000ff;">return</span><span style="color: #000000;"> stu;<br></span><span style="color: #008080;">44</span> <span style="color: #000000;">    }<br></span><span style="color: #008080;">45</span> <span style="color: #000000;">}<br></span><span style="color: #008080;">46</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> Test {<br></span><span style="color: #008080;">47</span><br><span style="color: #008080;">48</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String args[]) {<br></span><span style="color: #008080;">49</span><br><span style="color: #008080;">50</span>         Address addr = <span style="color: #0000ff;">new</span><span style="color: #000000;"> Address();<br></span><span style="color: #008080;">51</span>         addr.setAdd(“杭州市”<span style="color: #000000;">);<br></span><span style="color: #008080;">52</span>         Student stu1 = <span style="color: #0000ff;">new</span><span style="color: #000000;"> Student();<br></span><span style="color: #008080;">53</span>         stu1.setNumber(123<span style="color: #000000;">);<br></span><span style="color: #008080;">54</span> <span style="color: #000000;">        stu1.setAddr(addr);<br></span><span style="color: #008080;">55</span><br><span style="color: #008080;">56</span>         Student stu2 =<span style="color: #000000;"> (Student)stu1.clone();<br></span><span style="color: #008080;">57</span><br><span style="color: #008080;">58</span>         System.out.println(“学生1:” + stu1.getNumber() + “,地址:” +<span style="color: #000000;"> stu1.getAddr().getAdd());<br></span><span style="color: #008080;">59</span>         System.out.println(“学生2:” + stu2.getNumber() + “,地址:” +<span style="color: #000000;"> stu2.getAddr().getAdd());<br></span><span style="color: #008080;">60</span> <span style="color: #000000;">    }<br></span><span style="color: #008080;">61</span> }  </pre></p>
<p><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码" target="_blank" rel="external"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div></p>
<p></p><p>结果：</p><p></p>
<p></p><p class="alt">学生1:123,地址:杭州市&nbsp;&nbsp;</p><p></p>
<p></p><p>学生2:123,地址:杭州市 &nbsp;</p><p></p>
<p></p><p>&nbsp;</p><p></p>
<p></p><p>乍一看没什么问题，真的是这样吗？</p><p></p>
<p></p><p>我们在main方法中试着改变addr实例的地址。</p><p></p>
<p><div class="cnblogs_code"></div></p>
<p><pre>addr.setAdd(“西湖区”<span style="color: #000000;">);  </span></pre></p>
<p>System.out.println(“学生1:” + stu1.getNumber() + “,地址:” +<span style="color: #000000;"> stu1.getAddr().getAdd());<br>System.out.println(</span>“学生2:” + stu2.getNumber() + “,地址:” + stu2.getAddr().getAdd());  <br></p>
<p></p><p>结果：</p><p></p>
<p><div class="cnblogs_code"></div></p>
<p><pre>学生1:123<span style="color: #000000;">,地址:杭州市<br>学生2:</span>123<span style="color: #000000;">,地址:杭州市<br>学生1:</span>123<span style="color: #000000;">,地址:西湖区<br>学生2:</span>123,地址:西湖区  </pre><br></p>
<p></p><p>这就奇怪了，怎么两个学生的地址都改变了？</p><p></p>
<p></p><p>原因是浅复制只是复制了addr变量的引用，并没有真正的开辟另一块空间，将值复制后再将引用返回给新对象。</p><p></p>
<p></p><p>所以，为了达到真正的复制对象，而不是纯粹引用复制。我们需要将Address类可复制化，并且修改clone方法，完整代码如下：</p><p></p>
<p><div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码" target="_blank" rel="external"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div></div></p>
<p><pre><span style="color: #008080;"> 1</span> <span style="color: #0000ff;">package</span><span style="color: #000000;"> abc;<br></span><span style="color: #008080;"> 2</span><br><span style="color: #008080;"> 3</span> <span style="color: #0000ff;">class</span> Address <span style="color: #0000ff; background-color: #ffff99;">implements</span><span style="color: #000000;"><span style="background-color: #ffff99;"> Cloneable</span> {<br></span><span style="color: #008080;"> 4</span>     <span style="color: #0000ff;">private</span><span style="color: #000000;"> String add;<br></span><span style="color: #008080;"> 5</span><br><span style="color: #008080;"> 6</span>     <span style="color: #0000ff;">public</span><span style="color: #000000;"> String getAdd() {<br></span><span style="color: #008080;"> 7</span>         <span style="color: #0000ff;">return</span><span style="color: #000000;"> add;<br></span><span style="color: #008080;"> 8</span> <span style="color: #000000;">    }<br></span><span style="color: #008080;"> 9</span><br><span style="color: #008080;">10</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> setAdd(String add) {<br></span><span style="color: #008080;">11</span>         <span style="color: #0000ff;">this</span>.add =<span style="color: #000000;"> add;<br></span><span style="color: #008080;">12</span> <span style="color: #000000;">    }<br></span><span style="color: #008080;">13</span><br><span style="color: #008080;">14</span> <span style="color: #000000;">    @Override<br></span><span style="color: #008080;">15</span>     <span style="color: #0000ff;">public</span><span style="color: #000000;"> Object clone() {<br></span><span style="color: #008080;">16</span>         Address addr = <span style="color: #0000ff;">null</span><span style="color: #000000;">;<br></span><span style="color: #008080;">17</span>         <span style="color: #0000ff;">try</span><span style="color: #000000;">{<br></span><span style="color: #008080;">18</span>            <span style="background-color: #ffff99;"> addr = (Address)<span style="color: #0000ff;">super</span><span style="color: #000000;">.clone();<br></span></span><span style="color: #008080;">19</span>         }<span style="color: #0000ff;">catch</span><span style="color: #000000;">(CloneNotSupportedException e) {<br></span><span style="color: #008080;">20</span> <span style="color: #000000;">            e.printStackTrace();<br></span><span style="color: #008080;">21</span> <span style="color: #000000;">        }<br></span><span style="color: #008080;">22</span>         <span style="color: #0000ff;">return</span><span style="color: #000000;"> addr;<br></span><span style="color: #008080;">23</span> <span style="color: #000000;">    }<br></span><span style="color: #008080;">24</span> <span style="color: #000000;">}<br></span><span style="color: #008080;">25</span><br><span style="color: #008080;">26</span> <span style="color: #0000ff;">class</span> Student <span style="color: #0000ff; background-color: #ffff99;">implements</span><span style="color: #000000;"><span style="background-color: #ffff99;"> Cloneable</span>{<br></span><span style="color: #008080;">27</span>     <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> number;<br></span><span style="color: #008080;">28</span><br><span style="color: #008080;">29</span>     <span style="color: #0000ff;">private</span><span style="color: #000000;"> Address addr;<br></span><span style="color: #008080;">30</span><br><span style="color: #008080;">31</span>     <span style="color: #0000ff;">public</span><span style="color: #000000;"> Address getAddr() {<br></span><span style="color: #008080;">32</span>         <span style="color: #0000ff;">return</span><span style="color: #000000;"> addr;<br></span><span style="color: #008080;">33</span> <span style="color: #000000;">    }<br></span><span style="color: #008080;">34</span><br><span style="color: #008080;">35</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> setAddr(Address addr) {<br></span><span style="color: #008080;">36</span>         <span style="color: #0000ff;">this</span>.addr =<span style="color: #000000;"> addr;<br></span><span style="color: #008080;">37</span> <span style="color: #000000;">    }<br></span><span style="color: #008080;">38</span><br><span style="color: #008080;">39</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> getNumber() {<br></span><span style="color: #008080;">40</span>         <span style="color: #0000ff;">return</span><span style="color: #000000;"> number;<br></span><span style="color: #008080;">41</span> <span style="color: #000000;">    }<br></span><span style="color: #008080;">42</span><br><span style="color: #008080;">43</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> setNumber(<span style="color: #0000ff;">int</span><span style="color: #000000;"> number) {<br></span><span style="color: #008080;">44</span>         <span style="color: #0000ff;">this</span>.number =<span style="color: #000000;"> number;<br></span><span style="color: #008080;">45</span> <span style="color: #000000;">    }<br></span><span style="color: #008080;">46</span><br><span style="color: #008080;">47</span> <span style="color: #000000;">    @Override<br></span><span style="color: #008080;">48</span>     <span style="color: #0000ff;">public</span><span style="color: #000000;"> Object clone() {<br></span><span style="color: #008080;">49</span>         Student stu = <span style="color: #0000ff;">null</span><span style="color: #000000;">;<br></span><span style="color: #008080;">50</span>         <span style="color: #0000ff;">try</span><span style="color: #000000;">{<br></span><span style="color: #008080;">51</span>             stu = <span style="background-color: #ffff99;">(Student)<span style="color: #0000ff;">super</span>.clone()</span>;   <span style="color: #008000;">//</span><span style="color: #008000;">浅复制  </span><br><span style="color: #008080;">52</span>         }<span style="color: #0000ff;">catch</span><span style="color: #000000;">(CloneNotSupportedException e) {<br></span><span style="color: #008080;">53</span> <span style="color: #000000;">            e.printStackTrace();<br></span><span style="color: #008080;">54</span> <span style="color: #000000;">        }<br></span><span style="color: #008080;">55</span>         <span style="background-color: #ffff99;">stu.addr = (Address)addr.clone();</span>   <span style="color: #008000;">//</span><span style="color: #008000;">深度复制  </span><br><span style="color: #008080;">56</span>         <span style="color: #0000ff;">return</span><span style="color: #000000;"> stu;<br></span><span style="color: #008080;">57</span> <span style="color: #000000;">    }<br></span><span style="color: #008080;">58</span> <span style="color: #000000;">}<br></span><span style="color: #008080;">59</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> Test {<br></span><span style="color: #008080;">60</span><br><span style="color: #008080;">61</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String args[]) {<br></span><span style="color: #008080;">62</span><br><span style="color: #008080;">63</span>         Address addr = <span style="color: #0000ff;">new</span><span style="color: #000000;"> Address();<br></span><span style="color: #008080;">64</span>         addr.setAdd(“杭州市”<span style="color: #000000;">);<br></span><span style="color: #008080;">65</span>         Student stu1 = <span style="color: #0000ff;">new</span><span style="color: #000000;"> Student();<br></span><span style="color: #008080;">66</span>         stu1.setNumber(123<span style="color: #000000;">);<br></span><span style="color: #008080;">67</span> <span style="color: #000000;">        stu1.setAddr(addr);<br></span><span style="color: #008080;">68</span><br><span style="color: #008080;">69</span>         Student stu2 =<span style="color: #000000;"> (Student)stu1.clone();<br></span><span style="color: #008080;">70</span><br><span style="color: #008080;">71</span>         System.out.println(“学生1:” + stu1.getNumber() + “,地址:” +<span style="color: #000000;"> stu1.getAddr().getAdd());<br></span><span style="color: #008080;">72</span>         System.out.println(“学生2:” + stu2.getNumber() + “,地址:” +<span style="color: #000000;"> stu2.getAddr().getAdd());<br></span><span style="color: #008080;">73</span><br><span style="color: #008080;">74</span>         addr.setAdd(“西湖区”<span style="color: #000000;">);<br></span><span style="color: #008080;">75</span><br><span style="color: #008080;">76</span>         System.out.println(“学生1:” + stu1.getNumber() + “,地址:” +<span style="color: #000000;"> stu1.getAddr().getAdd());<br></span><span style="color: #008080;">77</span>         System.out.println(“学生2:” + stu2.getNumber() + “,地址:” +<span style="color: #000000;"> stu2.getAddr().getAdd());<br></span><span style="color: #008080;">78</span> <span style="color: #000000;">    }<br></span><span style="color: #008080;">79</span> }  </pre></p>
<p><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码" target="_blank" rel="external"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div></p>
<p></p><p>结果：</p><p></p>
<p><div class="cnblogs_code"></div></p>
<p><pre>学生1:123<span style="color: #000000;">,地址:杭州市<br>学生2:</span>123<span style="color: #000000;">,地址:杭州市<br>学生1:</span>123<span style="color: #000000;">,地址:西湖区<br>学生2:</span>123,地址:杭州市  </pre><br></p>
<p></p><p>这样结果就符合我们的想法了。</p><p></p>
<p></p><p>&nbsp;</p><p></p>
<p></p><p>最后我们可以看看API里其中一个实现了clone方法的类：</p><p></p>
<p></p><p>java.util.Date:</p><p></p>
<p><div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码" target="_blank" rel="external"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div></div></p>
<p><pre><span style="color: #008000;">/**</span><span style="color: #008000;"> </span></pre></p>
<ul>
<li>Return a copy of this object.<br><span style="color: #008000;">*/</span><br><span style="color: #0000ff;">public</span><span style="color: #000000;"> Object clone() {<br> Date d </span>= <span style="color: #0000ff;">null</span><span style="color: #000000;">;<br> </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> {  <pre><code>d &lt;/span&gt;= (Date)&lt;span style=&quot;color: #0000ff;&quot;&gt;super&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.clone();  
&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;if&lt;/span&gt; (cdate != &lt;span style=&quot;color: #0000ff;&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;) {  
    d.cdate &lt;/span&gt;=&lt;span style=&quot;color: #000000;&quot;&gt; (BaseCalendar.Date) cdate.clone();  
}  
</code></pre> } </span><span style="color: #0000ff;">catch</span> (CloneNotSupportedException e) {} <span style="color: #008000;">//</span><span style="color: #008000;"> Won’t happen  </span><br> <span style="color: #0000ff;">return</span><span style="color: #000000;"> d;<br>}  </span><br><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码" target="_blank" rel="external"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div><br><p>该类其实也属于深度复制。</p><br><p>参考文档：<span style="color: #0000ff;"><a href="http://blog.csdn.net/tounaobun/article/details/8491392" target="_blank" rel="external"><span style="color: #0000ff;">Java如何复制对象</span></a></span></p><br><div style="text-align: right"><a href="#_labelTop" style="color:blue">回到顶部</a><a name="_label2"></a></div><h2 id="blogTitle2">浅克隆和深克隆</h2><br><h3 id="blogTitle3">1、浅克隆</h3><br><p>在浅克隆中，如果原型对象的成员变量是值类型，将复制一份给克隆对象；如果原型对象的成员变量是引用类型，则将引用对象的地址复制一份给克隆对象，也就是说原型对象和克隆对象的成员变量指向相同的内存地址。</p><br><p>简单来说，在浅克隆中，当对象被复制时只复制它本身和其中包含的值类型的成员变量，而引用类型的成员对象并没有复制。</p><br><p><img title="浅克隆示意图" src="http://images2015.cnblogs.com/blog/690102/201607/690102-20160727132640216-1387063948.png" alt=""></p><br><p>在Java语言中，通过<span style="background-color: #ffff00;"><strong>覆盖Object类的clone()方法可以实现浅克隆</strong></span>。</p><br><h3 id="blogTitle4">2、深克隆</h3><br><p>在深克隆中，无论原型对象的成员变量是值类型还是引用类型，都将复制一份给克隆对象，深克隆将原型对象的所有引用对象也复制一份给克隆对象。</p><br><p>简单来说，在深克隆中，除了对象本身被复制外，对象所包含的所有成员变量也将复制。</p><br><p><img title="深克隆示意图" src="http://images2015.cnblogs.com/blog/690102/201607/690102-20160727132838528-120069275.png" alt=""></p><br><p>在Java语言中，如果需要<span style="background-color: #ffff00;"><strong>实现深克隆，可以通过<strong>覆盖Object类的clone()方法实现，也</strong>可以通过序列化(Serialization)等方式</strong></span>来实现。</p><br><p>（<strong>如果引用类型里面还包含很多引用类型，或者内层引用类型的类里面又包含引用类型，使用clone方法就会很麻烦。这时我们可以用序列化的方式来实现对象的深克隆。</strong>）</p><br><p>序列化就是将对象写到流的过程，写到流中的对象是原有对象的一个拷贝，而原对象仍然存在于内存中。通过序列化实现的拷贝不仅可以复制对象本身，而且可以复制其引用的成员对象，因此通过序列化将对象写到一个流中，再从流里将其读出来，可以实现深克隆。需要注意的是能够实现序列化的对象其类必须实现Serializable接口，否则无法实现序列化操作。</p><table border="0"><caption>扩展</caption><br><tbody><br><tr><br><td style="text-align: left;">Java语言提供的Cloneable接口和Serializable接口的代码非常简单，它们都是空接口，这种空接口也称为标识接口，标识接口中没有任何方法的定义，其作用是告诉JRE这些接口的实现类是否具有某个功能，如是否支持克隆、是否支持序列化等。</td><br></tr><br></tbody><br></table><br><div style="text-align: right"><a href="#_labelTop" style="color:blue">回到顶部</a><a name="_label3"></a></div><h2 id="blogTitle5">解决多层克隆问题</h2><br><p>如果引用类型里面还包含很多引用类型，或者内层引用类型的类里面又包含引用类型，使用clone方法就会很麻烦。这时我们可以用序列化的方式来实现对象的深克隆。</p><br><div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码" target="_blank" rel="external"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div><br><pre><span style="color: #008080;"> 1</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> Outer <span style="color: #0000ff;">implements</span><span style="color: #000000;"> Serializable{<br></span><span style="color: #008080;"> 2</span>   <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">final</span> <span style="color: #0000ff;">long</span> serialVersionUID = 369285298572941L;  <span style="color: #008000;">//</span><span style="color: #008000;">最好是显式声明ID</span><br><span style="color: #008080;"> 3</span>   <span style="color: #0000ff;">public</span><span style="color: #000000;"> Inner inner;<br></span><span style="color: #008080;"> 4</span> 　<span style="color: #99cc00;">//Discription:[深度复制方法,需要对象及对象所有的对象属性都实现序列化]　</span><br><span style="color: #008080;"> 5</span>   <span style="color: #0000ff;">public</span><span style="color: #000000;"> Outer myclone() {<br></span><span style="color: #008080;"> 6</span>       Outer outer = <span style="color: #0000ff;">null</span><span style="color: #000000;">;<br></span><span style="color: #008080;"> 7</span>       <span style="color: #0000ff;">try</span><span style="color: #000000;"> {<code class="java spaces">&nbsp;</code><span style="color: #99cc00;"><code class="java comments">// 将该对象序列化成流,因为写在流里的是对象的一个拷贝，而原对象仍然存在于JVM里面。所以利用这个特性可以实现对象的深拷贝</code><br></span></span><span style="color: #008080;"> 8</span>           ByteArrayOutputStream baos = <span style="color: #0000ff;">new</span><span style="color: #000000;"> ByteArrayOutputStream();<br></span><span style="color: #008080;"> 9</span>           ObjectOutputStream oos = <span style="color: #0000ff;">new</span><span style="color: #000000;"> ObjectOutputStream(baos);<br></span><span style="color: #008080;">10</span>           oos.writeObject(<span style="color: #0000ff;">this</span><span style="color: #000000;">);<br></span><span style="color: #008080;">11</span> 　　　　　　<span style="color: #99cc00;">// 将流序列化成对象</span><br><span style="color: #008080;">12</span>           ByteArrayInputStream bais = <span style="color: #0000ff;">new</span><span style="color: #000000;"> ByteArrayInputStream(baos.toByteArray());<br></span><span style="color: #008080;">13</span>           ObjectInputStream ois = <span style="color: #0000ff;">new</span><span style="color: #000000;"> ObjectInputStream(bais);<br></span><span style="color: #008080;">14</span>           outer =<span style="color: #000000;"> (Outer) ois.readObject();<br></span><span style="color: #008080;">15</span>       } <span style="color: #0000ff;">catch</span><span style="color: #000000;"> (IOException e) {<br></span><span style="color: #008080;">16</span> <span style="color: #000000;">          e.printStackTrace();<br></span><span style="color: #008080;">17</span>       } <span style="color: #0000ff;">catch</span><span style="color: #000000;"> (ClassNotFoundException e) {<br></span><span style="color: #008080;">18</span> <span style="color: #000000;">          e.printStackTrace();<br></span><span style="color: #008080;">19</span> <span style="color: #000000;">      }<br></span><span style="color: #008080;">20</span>       <span style="color: #0000ff;">return</span><span style="color: #000000;"> outer;<br></span><span style="color: #008080;">21</span> <span style="color: #000000;">  }<br></span><span style="color: #008080;">22</span> }</pre><br><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码" target="_blank" rel="external"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div></div><br><p>Inner也必须实现Serializable，否则无法序列化：</p><br><div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码" target="_blank" rel="external"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div><br><pre><span style="color: #008080;"> 1</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> Inner <span style="color: #0000ff;">implements</span><span style="color: #000000;"> Serializable{<br></span><span style="color: #008080;"> 2</span>   <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">final</span> <span style="color: #0000ff;">long</span> serialVersionUID = 872390113109L; <span style="color: #008000;">//</span><span style="color: #008000;">最好是显式声明ID</span><br><span style="color: #008080;"> 3</span>   <span style="color: #0000ff;">public</span> String name = “”<span style="color: #000000;">;<br></span><span style="color: #008080;"> 4</span><br><span style="color: #008080;"> 5</span>   <span style="color: #0000ff;">public</span><span style="color: #000000;"> Inner(String name) {<br></span><span style="color: #008080;"> 6</span>       <span style="color: #0000ff;">this</span>.name =<span style="color: #000000;"> name;<br></span><span style="color: #008080;"> 7</span> <span style="color: #000000;">  }<br></span><span style="color: #008080;"> 8</span><br><span style="color: #008080;"> 9</span> <span style="color: #000000;">  @Override<br></span><span style="color: #008080;">10</span>   <span style="color: #0000ff;">public</span><span style="color: #000000;"> String toString() {<br></span><span style="color: #008080;">11</span>       <span style="color: #0000ff;">return</span> “Inner的name值为：” +<span style="color: #000000;"> name;<br></span><span style="color: #008080;">12</span> <span style="color: #000000;">  }<br></span><span style="color: #008080;">13</span> }</pre><br><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="复制代码" target="_blank" rel="external"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码"></a></span></div></div><br><p>这样也能使两个对象在内存空间内完全独立存在，互不影响对方的值。</p><br><div style="text-align: right"><a href="#_labelTop" style="color:blue">回到顶部</a><a name="_label4"></a></div><h2 id="blogTitle6">总结</h2><br><p>实现对象克隆有两种方式：</p><br><p>  1). 实现Cloneable接口并重写Object类中的clone()方法；</p><br><p>  2). 实现Serializable接口，通过对象的序列化和反序列化实现克隆，可以实现真正的深度克隆。</p><br><table style="height: 105px; width: 976px;" border="1" cellspacing="0" cellpadding="0"><br><tbody><br><tr><br><td valign="top" width="568"><br><p><strong>注意：</strong>基于序列化和反序列化实现的克隆不仅仅是深度克隆，更重要的是通过泛型限定，可以检查出要克隆的对象是否支持序列化，这项检查是编译器完成的，不是在运行时抛出异常，这种是方案明显优于使用Object类的clone方法克隆对象。让问题在编译的时候暴露出来总是优于把问题留到运行时。</p><br></td><br></tr><br></tbody><br></table>
</li>
</ul>

      
    </div>

    <div>
      
        

      
    </div>

    <div>
      
        

      
    </div>

    <div>
      
        

      
    </div>

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/tags/java/" rel="tag"># java</a>
          
        </div>
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2017/07/12/SQL性能优化十条经验(转)/" rel="next" title="SQL性能优化十条经验(转)">
                <i class="fa fa-chevron-left"></i> SQL性能优化十条经验(转)
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2017/08/19/Redis学习笔记之一 ： 配置redis/" rel="prev" title="Redis学习笔记之一： 配置redis">
                Redis学习笔记之一： 配置redis <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          
  <div class="comments" id="comments">
    
  </div>


        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap" >
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
          <img class="site-author-image" itemprop="image"
               src="/images/xuwujing.png"
               alt="xuwujing" />
          <p class="site-author-name" itemprop="name">xuwujing</p>
           
              <p class="site-description motion-element" itemprop="description">The way of the future!</p>
          
        </div>
        <nav class="site-state motion-element">

          
            <div class="site-state-item site-state-posts">
              <a href="/archives/">
                <span class="site-state-item-count">56</span>
                <span class="site-state-item-name">日志</span>
              </a>
            </div>
          

          
            
            
            <div class="site-state-item site-state-categories">
              <a href="/categories/index.html">
                <span class="site-state-item-count">20</span>
                <span class="site-state-item-name">分类</span>
              </a>
            </div>
          

          
            
            
            <div class="site-state-item site-state-tags">
              <a href="/tags/index.html">
                <span class="site-state-item-count">36</span>
                <span class="site-state-item-name">标签</span>
              </a>
            </div>
          

        </nav>

        

        <div class="links-of-author motion-element">
          
            
              <span class="links-of-author-item">
                <a href="https://github.com/xuwujing" target="_blank" title="github">
                  
                    <i class="fa fa-fw fa-globe"></i>
                  
                  github
                </a>
              </span>
            
              <span class="links-of-author-item">
                <a href="http://blog.csdn.net/qazwsxpcm?viewmode=list" target="_blank" title="csdn">
                  
                    <i class="fa fa-fw fa-globe"></i>
                  
                  csdn
                </a>
              </span>
            
              <span class="links-of-author-item">
                <a href="https://home.cnblogs.com/u/xuwujing/" target="_blank" title="cnblogs">
                  
                    <i class="fa fa-fw fa-globe"></i>
                  
                  cnblogs
                </a>
              </span>
            
          
        </div>

        
        

        
        
          <div class="links-of-blogroll motion-element links-of-blogroll-inline">
            <div class="links-of-blogroll-title">
              <i class="fa  fa-fw fa-globe"></i>
              
            </div>
            <ul class="links-of-blogroll-list">
              
                <li class="links-of-blogroll-item">
                  <a href="http://www.woainia.site/" title="woainia" target="_blank">woainia</a>
                </li>
              
                <li class="links-of-blogroll-item">
                  <a href="http://cmsblogs.com/" title="chenssy" target="_blank">chenssy</a>
                </li>
              
            </ul>
          </div>
        

        


      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#blogTitle0"><span class="nav-number">1.</span> <span class="nav-text">为什么要克隆？</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#blogTitle1"><span class="nav-number">2.</span> <span class="nav-text">如何实现克隆</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#blogTitle2"><span class="nav-number">3.</span> <span class="nav-text">浅克隆和深克隆</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#blogTitle3"><span class="nav-number">3.1.</span> <span class="nav-text">1、浅克隆</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#blogTitle4"><span class="nav-number">3.2.</span> <span class="nav-text">2、深克隆</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#blogTitle5"><span class="nav-number">4.</span> <span class="nav-text">解决多层克隆问题</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#blogTitle6"><span class="nav-number">5.</span> <span class="nav-text">总结</span></a></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright" >
  
  &copy; 
  <span itemprop="copyrightYear">2017</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">xuwujing</span>
</div>


<div class="powered-by">
  由 <a class="theme-link" href="https://hexo.io">Hexo</a> 强力驱动
</div>

<div class="theme-info">
  主题 -
  <a class="theme-link" href="https://github.com/iissnan/hexo-theme-next">
    NexT.Muse
  </a>
</div>


        

        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  












  
  <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>

  
  <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>

  
  <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>

  
  <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.1"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.1"></script>



  
  

  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.1"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.1"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.1"></script>



  


  




	





  





  





  






  





  

  

  

  

  

  

</body>
</html>
